package com.forte.fortePoiUtils.reader;

import com.forte.fortePoiUtils.reader.HSSFReader.HSSFReader;

import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * Excel读取助手的抽象类<br>
 * 包含大量的方法和丰富的参数选择供使用<br>
 * 目前有两个核心方法：<br>
 * <ul>
 * 	<li>ExcelBean<T> read(Class<T>, Map<String , String> , String) → 以表名为基础进行读取</li>
 * 	<li>ExcelBean<T> read(Class<T>, Map<String , String> , int) → 以表索引为基础进行读取</li>
 * </ul>
 * 目前两个实现类：<br>
 * <ul>
 * <li>{@link HSSFReader} -> 对2003版本的excel文件进行操作</li>
 * <li>{@link HSSFReader} -> 对2010版本的excel文件进行操作</li>
 * </ul>
 * 
 * @author ForteScarlet
 * <div>
 *		<ul>
 *  		<li> ---><a href='https://gitee.com/ForteScarlet' target='_block'>码云个人地址</a></li> </li>
 *		</ul>
 * </div>
 */
public abstract class ExcelReader {

	/** 要读取的Excel文件的路径 */
	private InputStream stream;
	
	//// —————————————————————————————————————————————————————————————————— ////
	//// —————————————————————————————————————————————————————————————————— ////
	//// —————————————————————————————————————————————————————————————————— ////
	//// —————————————————————————————————————————————————————————————————— ////
	//// —————————————————————————————————————————————————————————————————— ////	
	
	/**
	 * 从Excel中读取数据并封装为JavaBean然后返回
	 * @param beanClass
	 * javaBean的Class对象
	 * @param result
	 * 表头与字段的映射
	 * @return
	 * 查询结果封装类
	 * @throws Exception
	 * @author ForteScarlet
	 */
	public <T> ExcelBean<T> read(Class<T> beanClass, Map<String , String> result) throws Exception{
		return read(beanClass , result , null);
	}
	
	/**
	 * 从Excel中读取数据并封装为JavaBean然后返回
	 * @param beanClass
	 * javaBean的Class对象
	 * @param sheetName
	 * 查询的表名
	 * @return
	 * 查询结果封装类
	 * @throws Exception
	 * @author ForteScarlet
	 */
	public <T> ExcelBean<T> read(Class<T> beanClass, String sheetName) throws Exception{
		return read(beanClass , null , sheetName);	
	}
	
	/**
	 * 从Excel中读取数据并封装为JavaBean然后返回
	 * @param beanClass
	 * javaBean的Class对象
	 * @param sheetIndex
	 * 查询的表索引
	 * @return
	 * 查询结果封装类
	 * @throws Exception
	 * @author ForteScarlet
	 */
	public <T> ExcelBean<T> read(Class<T> beanClass, int sheetIndex) throws Exception{
		return read(beanClass , null , sheetIndex);
	}


	
	
	//// —————————————————————————————————————————————————————————————————— ////
	//// —————————————————————————————————————————————————————————————————— ////
	//// —————————————————————————————————————————————————————————————————— ////
	//// —————————————————————————————————————————————————————————————————— ////
	//// —————————————————————————————————————————————————————————————————— ////	
	
	/** 
	 * 从Excel中读取数据并封装为JavaBean然后返回 - 通过表名,两个核心方法之一
	 * @param beanClass
	 * javaBean的Class对象
	 * @param result
	 * 表头与字段的映射
	 * @param sheetName
	 * 表名
	 * @return
	 * 查询结果封装类
	 * @throws Exception
	 * @author ForteScarlet
	 */
	public abstract <T> ExcelBean<T> read(Class<T> beanClass, Map<String , String> result , String sheetName) throws Exception;
	
	/** 
	 * 从Excel中读取数据并封装为JavaBean然后返回 - 通过表索引,两个核心方法之一
	 * @param beanClass
	 * javaBean的Class对象
	 * @param result
	 * 表头与字段的映射
	 * @param sheetIndex
	 * 表索引
	 * @return
	 * 查询结果封装类
	 * @throws Exception
	 * @author ForteScarlet
	 */
	public abstract <T> ExcelBean<T> read(Class<T> beanClass, Map<String , String> result , int sheetIndex) throws Exception;


    //// —————————————————————————————————————————————————————————————————— ////
    //// —————————————————————————————————————————————————————————————————— ////
    //// —————————————————————————————————————————————————————————————————— ////
    //// —————————————————————————————————————————————————————————————————— ////
    //// —————————————————————————————————————————————————————————————————— ////


    /**
     * 将数据转化为某个Bean
     * @param beanCreator	bean实例创建对象
     * @param injector		bean值注入函数
     * @param data			数据列
     * @param <T>			bean类型
     * @return				数据列表
     */
    protected static <T> List<T> toBean(Supplier<T> beanCreator, BiFunction<T, Map<String, String>, T> injector, List<Map<String, String>> data){
        //遍历数据
        return data.stream().map(m -> injector.apply(beanCreator.get(), m)).collect(Collectors.toList());
    }

    /**
     * 将数据转化为某个Bean
     * @param beanCreator	bean实例创建对象
     * @param injector		bean值注入函数
     * @param data			数据列
     * @param <T>			bean类型
     * @return				数据列表
     */
    protected static <T> T toBean(Supplier<T> beanCreator, BiFunction<T, Map<String, String>, T> injector, Map<String, String> data){
        //遍历数据
    	return injector.apply(beanCreator.get(), data);
    }

	/**
	 * 获取文件
	 * @return	获取excel文件输入流
	 * @author ForteScarlet
	 */
	protected InputStream getStream(){
		return stream;
	}
	
	/**
	 * 获取封装对象
	 * @param beanClass	bean的class泛型类型
	 * @return	获取封装数据
	 * @author ForteScarlet
	 */
	protected <T> ExcelBean<T> getExcelBean(Class<T> beanClass){
		return new ExcelBean<T>();
	}
	
	/**
	 * 构造方法
	 * @param stream	excel输入流
	 */
	public ExcelReader(InputStream stream){
		this.stream = stream;
	}
	
}
